package com.cfpamf.ms.insur.pay.aspect;

import com.cfpamf.common.ms.result.Result;
import com.cfpamf.ms.insur.pay.facade.constant.PayConstant;
import com.cfpamf.ms.insur.pay.facade.util.SignUtil;
import com.cfpamf.ms.insur.pay.service.SignKeyService;
import com.cfpamf.ms.insur.pay.util.HttpRequestUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Map;
import java.util.Objects;

/**
 * Create By zhengjing on 2019-10-21 15:21
 */
@ControllerAdvice
@Slf4j
public class ResponseBodyAddSignAdvice implements ResponseBodyAdvice {

    private static final String SIGN_TYPE_NAME = "com.cfpamf.common.ms.result.Result";

    @Autowired
    private ObjectMapper mapper;

    @Autowired
    private SignKeyService signKeyService;


    /**
     * 响应体拦截
     * 只拦截返回值为{@link com.cfpamf.common.ms.result.Result}的方法
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return StringUtils.startsWith(returnType.getGenericParameterType().getTypeName(), SIGN_TYPE_NAME);
    }

    /**
     * 获取返回值 并在header 中加入签名
     */
    @Override
    @SuppressWarnings("unchecked")
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        Result result = (Result) body;
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            /**
             * 获取当前请求系统的签名key
             */
            String sysCode = HttpRequestUtil.getHeader(PayConstant.HEADER_NAME_SYS);
            String sysKey = signKeyService.getKeyBySys(sysCode);

            Map<String, Object> map = mapper.convertValue(result.getData(), Map.class);
            String sign = SignUtil.MD5(map, sysKey);
            log.debug("开始生成签名{}:{}", sysCode, sign);
            response.getHeaders().add(PayConstant.HEADER_NAME_SIGN, sign);
        }
        return body;
    }

}
